package com.softwarecraftsmen.cachecontrol.caches;

import com.softwarecraftsmen.cachecontrol.CacheItem;
import static com.softwarecraftsmen.cachecontrol.CacheItem.createEmptyCacheItem;
import com.softwarecraftsmen.cachecontrol.Item;
import com.softwarecraftsmen.cachecontrol.keys.Key;
import org.jetbrains.annotations.NotNull;

import java.lang.ref.WeakReference;

public class MemoryReclaimingCache<V> extends AbstractComptrolledCache<V>
{
	private final ThreadSafeHashMapCache<V> threadSafeHashMapCache;

	public MemoryReclaimingCache(@NotNull final Key<V> identifier)
	{
		super(identifier);
		threadSafeHashMapCache = new ThreadSafeHashMapCache<V>(identifier);
	}

	@SuppressWarnings({"unchecked", "ConstantConditions"})
	@NotNull
	public Item<V> obtain(@NotNull final Key<V> key)
	{
		final Item<WeakReference<V>> item = (Item<WeakReference<V>>)threadSafeHashMapCache.obtain(key);
		if (item.isEmpty())
		{
			return createEmptyCacheItem(this, key);
		}
		return new CacheItem<V>(this, key, item.value().get());
	}

	@SuppressWarnings("unchecked")
	@NotNull
	public Item<V> store(final @NotNull Key<V> key, final @NotNull V value)
	{
		V weakValue = (V)new WeakReference<V>(value);
		threadSafeHashMapCache.store(key, weakValue);
		return new CacheItem<V>(this, key, value);
	}

	public void invalidate()
	{
		threadSafeHashMapCache.invalidate();
	}
}
